package ru.ifmo.ctd.year2008.notepad.client;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.StringTokenizer;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.WindowConstants;
import javax.swing.event.CaretEvent;
import javax.swing.event.CaretListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

public class GUI {
	final Dimension fieldSize = new Dimension(100, 15);
	private final static Dimension docSize = new Dimension(500, 500);
	private final Client client;
	 final JTextArea textArea;
	private final JButton newDoc;
	private final JButton open;
	private final JButton connect;
	private Thread reader;
	
	public String getText() {
		return textArea.getText();
	}
	
	public void setText(String text) {
		textArea.setText(text);
	}
	
	public GUI(Client client) {
		this.client = client;
		textArea = new JTextArea();		
		newDoc = new JButton("new");
		open = new JButton("open");
		connect = new JButton("connect");
		newDoc.setEnabled(false);
		open.setEnabled(false);
		open.addActionListener(new OpenListener());
		newDoc.addActionListener(new NewListener());
	}

    public static List<String> stringsList(String text) {
    	return Arrays.asList(text.split("\n", -1));
//        List<String> result = new ArrayList<String>();
//        StringTokenizer tok = new StringTokenizer(text, "\n");
//        while (tok.hasMoreTokens()) {
//            result.add(tok.nextToken());
//        }
//        System.out.println(result);
//        return result;
    }
	
	public void show() {
		JFrame frame = new JFrame("Shared Notepad");		
        frame.setLayout(new BorderLayout());
        
        textArea.setEditable(false);
        textArea.addCaretListener(new CaretListener() {
			@Override
			public void caretUpdate(CaretEvent arg0) {
				try {
					//TODO split text into lines
					//TODO do it not always but each several seconds
					if (textArea.isEditable()) {
						List<String> strings = stringsList(textArea.getText());
						client.sendDiff(strings);
					}
				} catch (IOException e) {
					e.printStackTrace();
					System.err.println("Editing failed.");
				}
			}        	
        });
       
        JPanel top = new JPanel(new FlowLayout());
        connect.addActionListener(new ConnectListener());
        
        top.add(connect);
        top.add(newDoc);
        top.add(open);
        
        frame.add(top, BorderLayout.NORTH);
        frame.add(textArea, BorderLayout.CENTER);
        
        frame.setPreferredSize(docSize);
      //frame.setResizable(false);
        
        frame.pack();
        frame.setVisible(true);
        frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
        
        frame.invalidate();
        frame.validate();
	}
	
	private class ConnectListener implements ActionListener {
		@Override
		public void actionPerformed(ActionEvent arg0) {			
			final JFrame frame = new JFrame("Connect to server");
			frame.setResizable(false);
			
			final JLabel ipLabel = new JLabel("ip: ");
			final JTextArea ip = new JTextArea("Enter ip");
			ip.setPreferredSize(fieldSize);
			
			final JLabel portLabel = new JLabel("port: ");
			final JTextArea port = new JTextArea("Enter port");
			port.setPreferredSize(fieldSize);
			
			final JButton ok = new JButton("Ok");
			
			ok.addActionListener(new ActionListener() {

				@Override
				public void actionPerformed(ActionEvent arg0) {
					int p = 0;
					try {
						p = Integer.parseInt(port.getText());
					} catch (NumberFormatException e) {
						JOptionPane.showMessageDialog(port,"Wrong port number format!");
						return;
					}					
					if (client.connect(ip.getText(), p) == null) {
						JOptionPane.showMessageDialog(ok,"Connection failed. Please, retry.");
						return;
					}
					newDoc.setEnabled(true);
					open.setEnabled(true);
					connect.setEnabled(false);
					frame.dispose();
				}
				
			});
			
			frame.setLayout(new FlowLayout());
			frame.add(portLabel);
			frame.add(port);
			frame.add(ipLabel);
			frame.add(ip);
			frame.add(ok);			
			
			frame.pack();
			frame.setVisible(true);
			frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
			frame.invalidate();
		    frame.validate();
		}		
	}
	
	private class OpenListener implements ActionListener {
		@Override
		public void actionPerformed(ActionEvent arg0) {
			JFrame frame = new JFrame("Available documents");
			frame.setResizable(false);
			killReader();
			String[] labels = client.getDocumentsList().toArray(new String[]{});
			JList list = new JList(labels);
			frame.setLayout(new BorderLayout());
			list.addListSelectionListener(new ChoiceListener(frame, labels));
			frame.add(list, BorderLayout.CENTER);
			frame.pack();
			frame.setVisible(true);
			frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
			frame.invalidate();
		    frame.validate();
		}		
	}
	
	private class ChoiceListener implements ListSelectionListener {
		private final JFrame parent;
		private final String[] labels;
		
		public ChoiceListener(JFrame parent, String[] labels) {
			this.labels = labels;
			this.parent = parent;
		}
		
		@Override
		public void valueChanged(ListSelectionEvent e) {
			textArea.setEditable(false);
			killReader();
			client.openToEdit(labels[e.getFirstIndex()]);
			manageReader();
//			textArea.setText(client.openToEdit(labels[e.getFirstIndex()]).toString());
			textArea.setEditable(true);
			parent.dispose();
		}
		
	}
	
	private class NewListener implements ActionListener {
		@Override
		public void actionPerformed(ActionEvent arg0) {
			JFrame frame = new JFrame("Create a new document");
			frame.setResizable(false);
			
			final JTextArea name = new JTextArea("Enter a name");
			name.setPreferredSize(fieldSize);
			JButton ok = new JButton("Ok");
			
			ok.addActionListener(new CreationListener(frame, name));
			
			frame.setLayout(new BorderLayout());
			frame.add(name, BorderLayout.CENTER);
			frame.add(ok, BorderLayout.EAST);
			
			frame.pack();
			frame.setVisible(true);
			frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
			frame.invalidate();
		    frame.validate();
		}		
	}
	
	private class CreationListener implements ActionListener {
		private final JFrame parent;
		private final JTextArea name;
		
		public CreationListener(JFrame parent, JTextArea name) {
			this.parent = parent;
			this.name = name;
		}
		
		@Override
		public void actionPerformed(ActionEvent arg0) {
			killReader();
			client.openToEdit(name.getText());
			manageReader();
		//	textArea.setText().toString());
			textArea.setEditable(true);
			parent.dispose();
		}
		
	}
	
	private void killReader() {
		if (reader != null) {
			reader.interrupt();
			client.disconnect();
			client.connect(client.host, client.port);
//			System.err.println("KILLING READER");
			reader = null;
		}
	}
	
	private void manageReader() {
		killReader();
		reader = new Thread(new ClientUpdateReader(client));
		reader.start();
	}
	
//	public static void main(String[] args) {
//		GUI gui = new GUI(new EmptyClient());
//		gui.show();
//	}
}
